package com.fr.base.core.antlr;

import com.fr.base.core.antlr.collections.impl.BitSet;
import com.fr.base.core.antlr.collections.impl.Vector;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;

public abstract class CodeGenerator
{
  protected Tool antlrTool;
  protected int tabs = 0;
  protected transient PrintWriter currentOutput;
  protected Grammar grammar = null;
  protected Vector bitsetsUsed;
  protected DefineGrammarSymbols behavior;
  protected LLkGrammarAnalyzer analyzer;
  protected CharFormatter charFormatter;
  protected boolean DEBUG_CODE_GENERATOR = false;
  protected static final int DEFAULT_MAKE_SWITCH_THRESHOLD = 2;
  protected static final int DEFAULT_BITSET_TEST_THRESHOLD = 4;
  protected static final int BITSET_OPTIMIZE_INIT_THRESHOLD = 8;
  protected int makeSwitchThreshold = 2;
  protected int bitsetTestThreshold = 4;
  private static boolean OLD_ACTION_TRANSLATOR = true;
  public static String TokenTypesFileSuffix = "TokenTypes";
  public static String TokenTypesFileExt = ".txt";

  protected void _print(String paramString)
  {
    if (paramString != null)
      this.currentOutput.print(paramString);
  }

  protected void _printAction(String paramString)
  {
    if (paramString == null)
      return;
    for (int i = 0; (i < paramString.length()) && (Character.isSpaceChar(paramString.charAt(i))); ++i);
    for (int j = paramString.length() - 1; (j > i) && (Character.isSpaceChar(paramString.charAt(j))); --j);
    char c = ';
    int k = i;
    while (true)
    {
      do
      {
        if (k > j)
          break label203;
        c = paramString.charAt(k);
        ++k;
        l = 0;
        switch (c)
        {
        case '\n':
          l = 1;
          break;
        case '\r':
          if ((k <= j) && (paramString.charAt(k) == '\n'))
            ++k;
          l = 1;
          break;
        default:
          this.currentOutput.print(c);
        }
      }
      while (l == 0);
      this.currentOutput.println();
      printTabs();
      while ((k <= j) && (Character.isSpaceChar(paramString.charAt(k))))
        ++k;
      int l = 0;
    }
    label203: this.currentOutput.println();
  }

  protected void _println(String paramString)
  {
    if (paramString != null)
      this.currentOutput.println(paramString);
  }

  public static boolean elementsAreRange(int[] paramArrayOfInt)
  {
    if (paramArrayOfInt.length == 0)
      return false;
    int i = paramArrayOfInt[0];
    int j = paramArrayOfInt[(paramArrayOfInt.length - 1)];
    if (paramArrayOfInt.length <= 2)
      return false;
    if (j - i + 1 > paramArrayOfInt.length)
      return false;
    int k = i + 1;
    for (int l = 1; l < paramArrayOfInt.length - 1; ++l)
    {
      if (k != paramArrayOfInt[l])
        return false;
      ++k;
    }
    return true;
  }

  protected String extractIdOfAction(Token paramToken)
  {
    return extractIdOfAction(paramToken.getText(), paramToken.getLine(), paramToken.getColumn());
  }

  protected String extractIdOfAction(String paramString, int paramInt1, int paramInt2)
  {
    paramString = removeAssignmentFromDeclaration(paramString);
    for (int i = paramString.length() - 2; i >= 0; --i)
      if ((!(Character.isLetterOrDigit(paramString.charAt(i)))) && (paramString.charAt(i) != '_'))
        return paramString.substring(i + 1);
    this.antlrTool.warning("Ill-formed action", this.grammar.getFilename(), paramInt1, paramInt2);
    return "";
  }

  protected String extractTypeOfAction(Token paramToken)
  {
    return extractTypeOfAction(paramToken.getText(), paramToken.getLine(), paramToken.getColumn());
  }

  protected String extractTypeOfAction(String paramString, int paramInt1, int paramInt2)
  {
    paramString = removeAssignmentFromDeclaration(paramString);
    for (int i = paramString.length() - 2; i >= 0; --i)
      if ((!(Character.isLetterOrDigit(paramString.charAt(i)))) && (paramString.charAt(i) != '_'))
        return paramString.substring(0, i + 1);
    this.antlrTool.warning("Ill-formed action", this.grammar.getFilename(), paramInt1, paramInt2);
    return "";
  }

  public abstract void gen();

  public abstract void gen(ActionElement paramActionElement);

  public abstract void gen(AlternativeBlock paramAlternativeBlock);

  public abstract void gen(BlockEndElement paramBlockEndElement);

  public abstract void gen(CharLiteralElement paramCharLiteralElement);

  public abstract void gen(CharRangeElement paramCharRangeElement);

  public abstract void gen(LexerGrammar paramLexerGrammar)
    throws IOException;

  public abstract void gen(OneOrMoreBlock paramOneOrMoreBlock);

  public abstract void gen(ParserGrammar paramParserGrammar)
    throws IOException;

  public abstract void gen(RuleRefElement paramRuleRefElement);

  public abstract void gen(StringLiteralElement paramStringLiteralElement);

  public abstract void gen(TokenRangeElement paramTokenRangeElement);

  public abstract void gen(TokenRefElement paramTokenRefElement);

  public abstract void gen(TreeElement paramTreeElement);

  public abstract void gen(TreeWalkerGrammar paramTreeWalkerGrammar)
    throws IOException;

  public abstract void gen(WildcardElement paramWildcardElement);

  public abstract void gen(ZeroOrMoreBlock paramZeroOrMoreBlock);

  protected void genTokenInterchange(TokenManager paramTokenManager)
    throws IOException
  {
    String str1 = paramTokenManager.getName() + TokenTypesFileSuffix + TokenTypesFileExt;
    this.currentOutput = this.antlrTool.openOutputFile(str1);
    println("// $ANTLR " + Tool.version + ": " + this.antlrTool.fileMinusPath(this.antlrTool.grammarFile) + " -> " + str1 + "$");
    this.tabs = 0;
    println(paramTokenManager.getName() + "    // output token vocab name");
    Vector localVector = paramTokenManager.getVocabulary();
    for (int i = 4; i < localVector.size(); ++i)
    {
      String str2 = (String)localVector.elementAt(i);
      if (this.DEBUG_CODE_GENERATOR)
        System.out.println("gen persistence file entry for: " + str2);
      if ((str2 != null) && (!(str2.startsWith("<"))))
      {
        Object localObject;
        if (str2.startsWith("\""))
        {
          localObject = (StringLiteralSymbol)paramTokenManager.getTokenSymbol(str2);
          if ((localObject != null) && (((StringLiteralSymbol)localObject).label != null))
            print(((StringLiteralSymbol)localObject).label + "=");
          println(str2 + "=" + i);
        }
        else
        {
          print(str2);
          localObject = paramTokenManager.getTokenSymbol(str2);
          if (localObject == null)
            this.antlrTool.warning("undefined token symbol: " + str2);
          else if (((TokenSymbol)localObject).getParaphrase() != null)
            print("(" + ((TokenSymbol)localObject).getParaphrase() + ")");
          println("=" + i);
        }
      }
    }
    this.currentOutput.close();
    this.currentOutput = null;
  }

  public String processStringForASTConstructor(String paramString)
  {
    return paramString;
  }

  public abstract String getASTCreateString(Vector paramVector);

  public abstract String getASTCreateString(GrammarAtom paramGrammarAtom, String paramString);

  protected String getBitsetName(int paramInt)
  {
    return "_tokenSet_" + paramInt;
  }

  public static String encodeLexerRuleName(String paramString)
  {
    return "m" + paramString;
  }

  public static String decodeLexerRuleName(String paramString)
  {
    if (paramString == null)
      return null;
    return paramString.substring(1, paramString.length());
  }

  public abstract String mapTreeId(String paramString, ActionTransInfo paramActionTransInfo);

  protected int markBitsetForGen(BitSet paramBitSet)
  {
    for (int i = 0; i < this.bitsetsUsed.size(); ++i)
    {
      BitSet localBitSet = (BitSet)this.bitsetsUsed.elementAt(i);
      if (paramBitSet.equals(localBitSet))
        return i;
    }
    this.bitsetsUsed.appendElement(paramBitSet.clone());
    return (this.bitsetsUsed.size() - 1);
  }

  protected void print(String paramString)
  {
    if (paramString != null)
    {
      printTabs();
      this.currentOutput.print(paramString);
    }
  }

  protected void printAction(String paramString)
  {
    if (paramString != null)
    {
      printTabs();
      _printAction(paramString);
    }
  }

  protected void println(String paramString)
  {
    if (paramString != null)
    {
      printTabs();
      this.currentOutput.println(paramString);
    }
  }

  protected void printTabs()
  {
    for (int i = 1; i <= this.tabs; ++i)
      this.currentOutput.print("\t");
  }

  protected abstract String processActionForSpecialSymbols(String paramString, int paramInt, RuleBlock paramRuleBlock, ActionTransInfo paramActionTransInfo);

  public String getFOLLOWBitSet(String paramString, int paramInt)
  {
    GrammarSymbol localGrammarSymbol = this.grammar.getSymbol(paramString);
    if (!(localGrammarSymbol instanceof RuleSymbol))
      return null;
    RuleBlock localRuleBlock = ((RuleSymbol)localGrammarSymbol).getBlock();
    Lookahead localLookahead = this.grammar.theLLkAnalyzer.FOLLOW(paramInt, localRuleBlock.endNode);
    String str = getBitsetName(markBitsetForGen(localLookahead.fset));
    return str;
  }

  public String getFIRSTBitSet(String paramString, int paramInt)
  {
    GrammarSymbol localGrammarSymbol = this.grammar.getSymbol(paramString);
    if (!(localGrammarSymbol instanceof RuleSymbol))
      return null;
    RuleBlock localRuleBlock = ((RuleSymbol)localGrammarSymbol).getBlock();
    Lookahead localLookahead = this.grammar.theLLkAnalyzer.look(paramInt, localRuleBlock);
    String str = getBitsetName(markBitsetForGen(localLookahead.fset));
    return str;
  }

  protected String removeAssignmentFromDeclaration(String paramString)
  {
    if (paramString.indexOf(61) >= 0)
      paramString = paramString.substring(0, paramString.indexOf(61)).trim();
    return paramString;
  }

  private void reset()
  {
    this.tabs = 0;
    this.bitsetsUsed = new Vector();
    this.currentOutput = null;
    this.grammar = null;
    this.DEBUG_CODE_GENERATOR = false;
    this.makeSwitchThreshold = 2;
    this.bitsetTestThreshold = 4;
  }

  public static String reverseLexerRuleName(String paramString)
  {
    return paramString.substring(1, paramString.length());
  }

  public void setAnalyzer(LLkGrammarAnalyzer paramLLkGrammarAnalyzer)
  {
    this.analyzer = paramLLkGrammarAnalyzer;
  }

  public void setBehavior(DefineGrammarSymbols paramDefineGrammarSymbols)
  {
    this.behavior = paramDefineGrammarSymbols;
  }

  protected void setGrammar(Grammar paramGrammar)
  {
    Token localToken2;
    reset();
    this.grammar = paramGrammar;
    if (this.grammar.hasOption("codeGenMakeSwitchThreshold"))
      try
      {
        this.makeSwitchThreshold = this.grammar.getIntegerOption("codeGenMakeSwitchThreshold");
      }
      catch (NumberFormatException localNumberFormatException1)
      {
        localToken2 = this.grammar.getOption("codeGenMakeSwitchThreshold");
        this.antlrTool.error("option 'codeGenMakeSwitchThreshold' must be an integer", this.grammar.getClassName(), localToken2.getLine(), localToken2.getColumn());
      }
    if (this.grammar.hasOption("codeGenBitsetTestThreshold"))
      try
      {
        this.bitsetTestThreshold = this.grammar.getIntegerOption("codeGenBitsetTestThreshold");
      }
      catch (NumberFormatException localNumberFormatException2)
      {
        localToken2 = this.grammar.getOption("codeGenBitsetTestThreshold");
        this.antlrTool.error("option 'codeGenBitsetTestThreshold' must be an integer", this.grammar.getClassName(), localToken2.getLine(), localToken2.getColumn());
      }
    if (this.grammar.hasOption("codeGenDebug"))
    {
      Token localToken1 = this.grammar.getOption("codeGenDebug");
      if (localToken1.getText().equals("true"))
        this.DEBUG_CODE_GENERATOR = true;
      else if (localToken1.getText().equals("false"))
        this.DEBUG_CODE_GENERATOR = false;
      else
        this.antlrTool.error("option 'codeGenDebug' must be true or false", this.grammar.getClassName(), localToken1.getLine(), localToken1.getColumn());
    }
  }

  public void setTool(Tool paramTool)
  {
    this.antlrTool = paramTool;
  }
}